"""
DeepSeek LLM提供商实现
支持DeepSeek API（兼容OpenAI格式）
"""
from typing import Dict, Any, List
from loguru import logger
import httpx
from openai import OpenAI

from storyforge.providers.base import ProviderBase


class LLMDeepSeekProvider(ProviderBase):
    """DeepSeek LLM提供商"""
    
    def __init__(self, config: Dict[str, Any]):
        """
        初始化DeepSeek提供商
        
        Args:
            config: 配置字典
        """
        super().__init__(config)
        
        # 从全局配置获取默认值
        from storyforge.config import get_config
        global_config = get_config()
        llm_config = global_config.llm
        
        self.api_key = config.get("apiKey")
        
        # 处理 base_url
        self.base_url = config.get("base_url") or config.get("endpoint")
        if not self.base_url:
            self.base_url = "https://api.deepseek.com"
        

        self.model = config.get("model", "deepseek-chat")
        
        # 从提供商配置或全局llm配置读取参数
        self.timeout = config.get("timeout") or llm_config.requestTimeout
        self.max_retries = config.get("maxRetries") or llm_config.maxRetries
        self.default_temperature = config.get("temperature") or llm_config.defaultTemperature
        self.default_max_tokens = config.get("maxOutputTokens") or llm_config.defaultMaxTokens
        
        if not self.api_key:
            raise ValueError("DeepSeek API密钥未配置")

        # 配置代理
        proxy_config = self._build_proxy_config(config)
        http_client = None
        
        # 只有在配置了代理时才创建自定义httpx客户端
        # 否则让OpenAI使用默认客户端
        if proxy_config:
            proxies = {}
            if "http" in proxy_config:
                proxies["http://"] = proxy_config["http"]
            if "https" in proxy_config:
                proxies["https://"] = proxy_config["https"]
            
            if proxies:
                http_client = httpx.Client(
                    proxies=proxies,
                    # 注意：timeout在Client中设置，也在OpenAI中设置，OpenAI的timeout优先级更高(如果传了)
                )

        # 初始化 OpenAI 客户端
        self.client = OpenAI(
            api_key=self.api_key,
            base_url=self.base_url,
            timeout=self.timeout,
            max_retries=self.max_retries,
            http_client=http_client
        )
    
    def _build_proxy_config(self, config: Dict[str, Any]):
        """
        构建代理配置（优先使用提供商级别，否则使用全局配置）
        
        Args:
            config: 提供商配置字典
            
        Returns:
            代理配置字典，格式: {"http": "http://proxy:port", "https": "https://proxy:port"}，未配置返回None
        """
        from storyforge.config import get_config
        
        # 优先使用提供商级别的代理配置
        proxy_config = config.get("proxy")
        if proxy_config:
            return proxy_config
        
        # 使用全局代理配置
        global_config = get_config()
        if global_config.proxy:
            return {
                "http": global_config.proxy.http,
                "https": global_config.proxy.https
            }
        
        return None
    
    def name(self) -> str:
        """返回提供商名称"""
        return "deepseek"
    
    def generate(
        self,
        messages: List[Dict[str, str]],
        temperature: float = None,
        max_tokens: int = None,
        **kwargs
    ) -> str:
        """
        生成文本（DeepSeek兼容OpenAI格式）
        
        Args:
            messages: 消息列表
            temperature: 温度参数（None则使用默认值）
            max_tokens: 最大token数（None则使用默认值）
            **kwargs: 其他参数
            
        Returns:
            生成的文本
        """
        # 准备参数
        params = {
            "model": self.model,
            "messages": messages,
            "temperature": temperature if temperature is not None else self.default_temperature,
            "max_tokens": max_tokens if max_tokens is not None else self.default_max_tokens,
        }
        
        # 添加response_format（如果指定）
        response_format = kwargs.get("response_format")
        if response_format:
            params["response_format"] = response_format
            
        # 如果kwargs中有其他openai支持的参数，可以在这里添加
        # 例如 stream, top_p 等，目前暂不自动传递所有kwargs以防报错
        
        try:
            # 计算请求信息（用于日志）
            msg_head = messages[:20] if len(messages) >= 20 else messages
            msg_tail = messages[-20:] if len(messages) >= 20 else messages
            logger.debug(f"调用DeepSeek API: {self.model}")
            logger.debug(f"  消息长度: {len(messages)}, 温度: {params['temperature']}")
            logger.debug(f"  消息头部前20字符: {msg_head}")
            logger.debug(f"  消息尾部后20字符: {msg_tail}")
            
            import time
            start_time = time.time()
            
            response = self.client.chat.completions.create(**params)
            
            elapsed_time = time.time() - start_time
            
            content = response.choices[0].message.content
            
            # 记录使用情况
            usage = response.usage
            prompt_tokens = usage.prompt_tokens if usage else 0
            completion_tokens = usage.completion_tokens if usage else 0
            total_tokens = usage.total_tokens if usage else 0
            
            logger.info(f"DeepSeek API调用成功")
            logger.info(f"  模型: {self.model}")
            logger.info(f"  耗时: {elapsed_time:.2f}秒")
            logger.info(f"  输出: {len(content) if content else 0} 字符")
            logger.info(f"  Token使用: 输入={prompt_tokens}, 输出={completion_tokens}, 总计={total_tokens}")
            
            # 记录性能日志（TRACE级别）
            logger.bind(duration=elapsed_time).trace(
                f"API调用: DeepSeek {self.model} | "
                f"输入tokens={prompt_tokens} | 输出tokens={completion_tokens}"
            )
            
            return content
            
        except Exception as e:
            logger.error(f"DeepSeek生成失败: {e}")
            logger.exception("API调用异常详情:")
            raise
    
    def submit(self, payload: Dict[str, Any]) -> str:
        """提交任务（同步调用）"""
        messages = payload.get("messages", [])
        temperature = payload.get("temperature")
        max_tokens = payload.get("max_tokens")
        
        # 注意：这里将payload作为kwargs传递
        # generate方法目前只提取 response_format
        result = self.generate(messages, temperature, max_tokens, **payload)
        return result
    
    def poll(self, external_job_id: str) -> Dict[str, Any]:
        """轮询任务状态（同步调用，直接返回结果）"""
        return {
            "status": "succeeded",
            "result": external_job_id
        }
